feat: add sandbox worker support with multi-arch Docker builds#6
feat: add sandbox worker support with multi-arch Docker builds#6andersonleal merged 4 commits intomainfrom
Conversation
… and update example configurations Updated the Dockerfile to support multi-architecture builds by adding necessary cross-compilation tools and adjusting the build process. Modified example configuration files to include new environment variables and updated the package.json to switch the development script from Bun to npm, ensuring compatibility with TypeScript. Added logging for custom environment variables in the TypeScript worker. feat(example-typescript): replace Bun with npm in image resize demo worker setup Switches to npm for dependency and script management. Updates the package manager and runtime scripts, removes Bun-specific setup, and adds a new lockfile. refactor(example-rust): remove Rust image resize demo worker fix(example-python): use asyncio.run with Event for keepalive (Python 3.14 compat) fix(example-python): keep process alive with event loop to receive invocations fix(example-python): use InitOptions instead of raw dict for register_worker feat(example-python): add Python image resize demo worker Mirrors the TypeScript example with health and thumbnail endpoints. Uses iii-sdk Python package to connect to the engine and invoke image_resize::resize via SDK channels. fix(image-resize): skip config.yaml load when file doesn't exist docs: add Podman runtime implementation plan 6-task plan covering PodmanAdapter creation, Docker/Sandbox removal, microsandbox delegation update, managed.rs simplification, CLI cleanup, and full build verification. docs: add Podman runtime design spec Replace Docker with Podman as sole container runtime. Remove SandboxAdapter and --isolation flag. Dev mode stays microsandbox-only. Managed workers use Podman with auto podman-machine management on macOS. refactor: all manifests use iii: v1 (no v2 version needed) fix(example-python): install iii-sdk directly instead of building from pyproject.toml pip install . triggers a full build that spawns subprocesses hitting the microsandbox 1024 fd limit. Install the SDK dep directly and use PYTHONPATH to make the local module importable. fix(example-python): use non-editable pip install (editable hits fd limit in msb) fix(example-python): use system pip directly, skip venv (ensurepip broken in msb) fix(example-python): remove sudo from setup, fix invalid pyproject.toml scripts - Drop setup script: msb python image has Python 3.14, venv, and pip - Remove invalid [project.scripts] entry that caused pip install failure (must be entrypoint reference, not shell command) fix(example): remove apt-get from bun setup, microsandbox node image has curl feat: upgrade all example manifests to iii.worker.yaml v2 format - TypeScript/Bun, Python, Rust examples now use v2 schema - Plain MB for memory instead of K8s-style (512Mi → 512) - scripts section replaces dependencies section - III_URL/III_ENGINE_URL removed from env (auto-injected by engine) docs: add microsandbox runtime design spec Microsandbox as primary strong-isolation runtime, Docker Sandbox as fallback. iii.worker.yaml v2 format with structured runtime declarations and auto-detection. Solves WebSocket proxy issue with Docker Sandbox. docs(example-rust): document sandbox limitation on Apple Silicon (rustc SIGILL) fix(example-rust): use debug build in sandbox to avoid SIGILL on ARM VM fix(example-rust): cargo clean before build to avoid cross-platform target corruption fix(examples): use sudo for apt-get in sandbox setup fix(example-rust): install build-essential for cc linker in sandbox fix(example-rust): use iii-sdk from crates.io instead of local path Path deps aren't visible inside the sandbox since only the project workspace directory is synced. fix(example-python): use venv for pip install inside sandbox VM feat(examples): add Python and Rust image-resize demo workers Both mirror the Node.js example — health check + thumbnail endpoints connecting to image_resize::resize via channels. Each includes iii.worker.yaml for sandbox dev with `iii worker dev`. feat(example): add iii.worker.yaml for sandbox dev environment Declares bun runtime setup, install, and run commands so 'iii worker dev' knows how to build the sandbox VM. docs: add Docker Sandbox runtime design spec Replaces Firecracker with Docker Sandboxes for strong isolation. microVM isolation on Mac/Windows without KVM. Two runtimes (docker, sandbox), two deployment modes (per-worker sandbox, engine-in-sandbox). refactor(launcher): remove iii-launcher module and associated files This commit deletes the iii-launcher module, including its Cargo.toml, Cargo.lock, and source files. The removal streamlines the project structure as the launcher functionality is no longer needed. feat(launcher): add health check loop with exponential backoff restarts feat(launcher): return restart info in status response feat(launcher): add configurable stop timeout to Docker adapter SIGTERM + grace period before SIGKILL: 30s for explicit stops, 10s for pre-start cleanup. feat(launcher): add restart tracking fields to ManagedWorker state docs: add Phase 2A runtime hardening implementation plan 6 tasks: state enrichment, Docker stop timeout, resource enforcement, health check loop, enriched status output, SDK graceful shutdown drain. docs: add Phase 2A runtime hardening design spec Resource enforcement from manifests, health check loop with exponential backoff restarts, graceful shutdown via Docker SIGTERM + SDK drain. feat(launcher): add iii-launcher worker with DockerAdapter RuntimeAdapter trait, Docker CLI implementation, launcher state persistence, and 5 function handlers (pull, start, stop, status, logs). feat(image-resize): add Dockerfile with embedded manifest, prepare SDK manifest integration feat(ci): add OCI build workflow, registry v2 format, switch release from binary to OCI feat(image-resize): emit iii worker manifest in YAML format docs: add Phase 1 implementation plan for iii worker abstraction layer 13 tasks covering manifest types, protocol extensions, manifest-driven readiness, SDK support, OCI build, launcher worker with Docker adapter, CLI commands, registry v2, CI/CD workflow, and E2E verification. docs: add iii worker abstraction layer design spec Design for decoupling worker artifacts and contracts from runtime substrates. OCI images as canonical packaging, dedicated launcher sidecar, manifest-driven readiness, and backward-compatible protocol extensions.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds containerization for the image-resize worker (multi-arch Dockerfile and .dockerignore), replaces in-repo example worker configs with container-based manifests, updates the example TypeScript demo and tooling, and adjusts a manifest test to use the crate package version constant. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…dynamic versioning
…ut worker settings
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
image-resize/Dockerfile (1)
6-13: Use--no-install-recommendsin both apt installs.These stages only need the named packages; recommended packages just add size and attack surface.
💡 Proposed fix
-RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config \ libssl-dev \ gcc-x86-64-linux-gnu \ gcc-aarch64-linux-gnu \ libc6-dev-amd64-cross \ libc6-dev-arm64-cross \ && rm -rf /var/lib/apt/lists/* @@ -RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/*Also applies to: 43-43
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@image-resize/Dockerfile` around lines 6 - 13, The apt installs in the Dockerfile RUN steps currently use apt-get install -y without suppressing recommends; update both RUN commands (the apt-get install lines that install pkg-config, libssl-dev, gcc-x86-64-linux-gnu, gcc-aarch64-linux-gnu, libc6-dev-amd64-cross, libc6-dev-arm64-cross and the other install at line ~43) to include --no-install-recommends (i.e., apt-get install -y --no-install-recommends ...) so only the named packages are installed and extra recommended packages are avoided, keeping the rest of the command structure (apt-get update && ... && rm -rf /var/lib/apt/lists/*) intact.image-resize/.dockerignore (1)
1-6: Excludeimage-resize/example/from this build context too.
image-resize/Dockerfilenever copies anything fromimage-resize/example/, so sending that directory to buildx just adds upload time and cache noise.💡 Proposed fix
target/ .git/ *.md docs/ iii-launcher/ .github/ +example/🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@image-resize/.dockerignore` around lines 1 - 6, Add the build-context exclusion for the example directory by updating the .dockerignore to include a rule for the example/ folder so it is not sent to the Docker build context; specifically, add a line excluding "example/" (and "example/**" if you prefer recursive coverage) to the existing .dockerignore entries so the Dockerfile won't cause the example files to be uploaded during build.image-resize/example/iii.workers.yaml (1)
3-3: Pin a versioned image here instead oflatest.
latestmakes this example non-reproducible and can silently change the worker bits between runs. A release tag or digest is safer now that multi-arch images are being published.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@image-resize/example/iii.workers.yaml` at line 3, Replace the non-reproducible image reference under the image key in iii.workers.yaml (currently "docker.io/andersonofl/image-resize:latest") with a specific release tag or a digest (for example a semver tag like v1.2.3 or a sha256 digest) so the worker image is immutable and reproducible; update the image value to the chosen tag/digest and commit the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@image-resize/Dockerfile`:
- Around line 22-39: The manifest generation is using the host compile-time
TARGET (env!("TARGET")) because cargo run --release -- --manifest is invoked
before TARGET_TRIPLE is computed; resolve TARGET_TRIPLE from TARGETARCH first
(the same case block that sets TARGET_TRIPLE and the cargo linker env vars) and
then invoke the manifest generation with that target (pass the computed
TARGET_TRIPLE into the manifest step—e.g. export or pass as an argument to the
cargo run invocation that generates the manifest) so
image-resize/src/manifest.rs observes the intended target rather than the
builder host.
- Around line 48-51: The Dockerfile hard-codes the --url flag so the ENV
III_ENGINE_URL has no effect; either update the Clap argument in
image-resize/src/main.rs to read from the environment (e.g., add env =
"III_ENGINE_URL" to the struct field or use Arg::env("III_ENGINE_URL") for the
URL option) so the binary picks up III_ENGINE_URL, or change the Dockerfile’s
ENTRYPOINT/CMD to perform shell expansion of the env var (e.g., emit the --url
value from ${III_ENGINE_URL}) so the runtime URL comes from the environment.
- Around line 41-51: The final Dockerfile image runs as root; create a non-root
runtime user and switch to it before ENTRYPOINT/CMD to reduce privileges: add a
user (e.g., iii or workeruser) in the final stage, chown the copied /worker
binary and /iii/worker.yaml to that user (ensure the COPY from=builder preserves
ownership or perform chown), and add a USER instruction so ENTRYPOINT
["/worker"] and CMD remain unchanged but run unprivileged; also ensure the
binary is executable by that user and any required runtime dirs have appropriate
permissions.
In `@image-resize/example/config.yaml`:
- Around line 1-6: The commented example in config.yaml uses the old list-style
"workers" block with "config" (e.g., workers: - name: image-resize / config:)
which no longer matches the new config shape; update the snippet to follow the
new structure used in iii.workers.yaml (e.g., workers.image-resize.env) and
expose the environment variables (III_ENGINE_URL, III_API_URL) under
workers.image-resize.env so that the example aligns with the new format and
users copying it get the correct keys.
---
Nitpick comments:
In `@image-resize/.dockerignore`:
- Around line 1-6: Add the build-context exclusion for the example directory by
updating the .dockerignore to include a rule for the example/ folder so it is
not sent to the Docker build context; specifically, add a line excluding
"example/" (and "example/**" if you prefer recursive coverage) to the existing
.dockerignore entries so the Dockerfile won't cause the example files to be
uploaded during build.
In `@image-resize/Dockerfile`:
- Around line 6-13: The apt installs in the Dockerfile RUN steps currently use
apt-get install -y without suppressing recommends; update both RUN commands (the
apt-get install lines that install pkg-config, libssl-dev, gcc-x86-64-linux-gnu,
gcc-aarch64-linux-gnu, libc6-dev-amd64-cross, libc6-dev-arm64-cross and the
other install at line ~43) to include --no-install-recommends (i.e., apt-get
install -y --no-install-recommends ...) so only the named packages are installed
and extra recommended packages are avoided, keeping the rest of the command
structure (apt-get update && ... && rm -rf /var/lib/apt/lists/*) intact.
In `@image-resize/example/iii.workers.yaml`:
- Line 3: Replace the non-reproducible image reference under the image key in
iii.workers.yaml (currently "docker.io/andersonofl/image-resize:latest") with a
specific release tag or a digest (for example a semver tag like v1.2.3 or a
sha256 digest) so the worker image is immutable and reproducible; update the
image value to the chosen tag/digest and commit the change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6bfa68be-713e-4d59-aeef-2db2501cf5ae
⛔ Files ignored due to path filters (1)
image-resize/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (8)
image-resize/.dockerignoreimage-resize/Dockerfileimage-resize/example/config.yamlimage-resize/example/iii.tomlimage-resize/example/iii.worker.yamlimage-resize/example/iii.workers.yamlimage-resize/example/package.jsonimage-resize/example/src/iii.ts
💤 Files with no reviewable changes (1)
- image-resize/example/iii.toml
| RUN cargo run --release -- --manifest > /build/worker.yaml | ||
|
|
||
| RUN case "${TARGETARCH}" in \ | ||
| amd64) \ | ||
| TARGET_TRIPLE="x86_64-unknown-linux-gnu"; \ | ||
| export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc; \ | ||
| ;; \ | ||
| arm64) \ | ||
| TARGET_TRIPLE="aarch64-unknown-linux-gnu"; \ | ||
| export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc; \ | ||
| ;; \ | ||
| *) \ | ||
| echo "Unsupported TARGETARCH=${TARGETARCH}" >&2; \ | ||
| exit 1; \ | ||
| ;; \ | ||
| esac && \ | ||
| cargo build --release --target "${TARGET_TRIPLE}" && \ | ||
| cp "target/${TARGET_TRIPLE}/release/image-resize" /worker |
There was a problem hiding this comment.
The generated manifest will advertise the build platform, not the target platform.
Line 22 runs cargo run --release -- --manifest before TARGETARCH is resolved, and image-resize/src/manifest.rs derives supported_targets from env!("TARGET"). An amd64 builder producing an arm64 image will still copy a manifest that says x86_64-unknown-linux-gnu.
Resolve TARGET_TRIPLE first and pass that into manifest generation instead of relying on the host build target.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@image-resize/Dockerfile` around lines 22 - 39, The manifest generation is
using the host compile-time TARGET (env!("TARGET")) because cargo run --release
-- --manifest is invoked before TARGET_TRIPLE is computed; resolve TARGET_TRIPLE
from TARGETARCH first (the same case block that sets TARGET_TRIPLE and the cargo
linker env vars) and then invoke the manifest generation with that target (pass
the computed TARGET_TRIPLE into the manifest step—e.g. export or pass as an
argument to the cargo run invocation that generates the manifest) so
image-resize/src/manifest.rs observes the intended target rather than the
builder host.
| FROM debian:bookworm-slim | ||
|
|
||
| RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| COPY --from=builder /worker /worker | ||
| COPY --from=builder /build/worker.yaml /iii/worker.yaml | ||
|
|
||
| ENV III_ENGINE_URL=ws://host.containers.internal:49134 | ||
|
|
||
| ENTRYPOINT ["/worker"] | ||
| CMD ["--url", "ws://host.containers.internal:49134"] |
There was a problem hiding this comment.
Run the final image as a non-root user.
The runtime stage never drops root. For a sandbox worker, that's an unnecessary privilege boundary loss.
💡 Proposed fix
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
+RUN useradd --system --uid 10001 --create-home iii \
+ && mkdir -p /iii \
+ && chown iii:iii /iii
-COPY --from=builder /worker /worker
-COPY --from=builder /build/worker.yaml /iii/worker.yaml
+COPY --from=builder --chown=iii:iii /worker /worker
+COPY --from=builder --chown=iii:iii /build/worker.yaml /iii/worker.yaml
ENV III_ENGINE_URL=ws://host.containers.internal:49134
+USER iii
ENTRYPOINT ["/worker"]
CMD ["--url", "ws://host.containers.internal:49134"]📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| FROM debian:bookworm-slim | |
| RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* | |
| COPY --from=builder /worker /worker | |
| COPY --from=builder /build/worker.yaml /iii/worker.yaml | |
| ENV III_ENGINE_URL=ws://host.containers.internal:49134 | |
| ENTRYPOINT ["/worker"] | |
| CMD ["--url", "ws://host.containers.internal:49134"] | |
| FROM debian:bookworm-slim | |
| RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* | |
| RUN useradd --system --uid 10001 --create-home iii \ | |
| && mkdir -p /iii \ | |
| && chown iii:iii /iii | |
| COPY --from=builder --chown=iii:iii /worker /worker | |
| COPY --from=builder --chown=iii:iii /build/worker.yaml /iii/worker.yaml | |
| ENV III_ENGINE_URL=ws://host.containers.internal:49134 | |
| USER iii | |
| ENTRYPOINT ["/worker"] | |
| CMD ["--url", "ws://host.containers.internal:49134"] |
🧰 Tools
🪛 Trivy (0.69.3)
[error] 43-43: 'apt-get' missing '--no-install-recommends'
'--no-install-recommends' flag is missed: 'apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*'
Rule: DS-0029
(IaC/Dockerfile)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@image-resize/Dockerfile` around lines 41 - 51, The final Dockerfile image
runs as root; create a non-root runtime user and switch to it before
ENTRYPOINT/CMD to reduce privileges: add a user (e.g., iii or workeruser) in the
final stage, chown the copied /worker binary and /iii/worker.yaml to that user
(ensure the COPY from=builder preserves ownership or perform chown), and add a
USER instruction so ENTRYPOINT ["/worker"] and CMD remain unchanged but run
unprivileged; also ensure the binary is executable by that user and any required
runtime dirs have appropriate permissions.
| ENV III_ENGINE_URL=ws://host.containers.internal:49134 | ||
|
|
||
| ENTRYPOINT ["/worker"] | ||
| CMD ["--url", "ws://host.containers.internal:49134"] |
There was a problem hiding this comment.
III_ENGINE_URL cannot actually reconfigure this image.
image-resize/src/main.rs only consumes --url, and Line 51 hard-codes that flag in CMD. Setting III_ENGINE_URL from image-resize/example/iii.workers.yaml or the container environment has no effect.
Either bind the Clap arg to env = "III_ENGINE_URL" or expand the env in the entrypoint.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@image-resize/Dockerfile` around lines 48 - 51, The Dockerfile hard-codes the
--url flag so the ENV III_ENGINE_URL has no effect; either update the Clap
argument in image-resize/src/main.rs to read from the environment (e.g., add env
= "III_ENGINE_URL" to the struct field or use Arg::env("III_ENGINE_URL") for the
URL option) so the binary picks up III_ENGINE_URL, or change the Dockerfile’s
ENTRYPOINT/CMD to perform shell expansion of the env var (e.g., emit the --url
value from ${III_ENGINE_URL}) so the runtime URL comes from the environment.
…and enhance CORS options - Introduced new worker definitions for iii-stream and iii-http with specific configurations. - Enhanced CORS settings to include additional allowed methods and clarified allowed origins. - Removed deprecated module definitions for a cleaner configuration structure.
Summary
image-resizeworker — supports bothamd64andarm64via cross-compilation with platform-specific linkersiii.worker.yaml(defines the worker sandbox runtime: language, entry, resources, scripts) andiii.workers.yaml(declares external worker images with env/resource constraints), replacing the previousiii.tomlapproachbuntonode --import tsx, addstsxdev dependency, updates package scope to@iii, and comments out the old inline worker config inconfig.yamlType of Change
Checklist
cargo run --release -- --manifestAdditional Context
This PR introduces the foundational configuration for running workers as sandboxed containers. The
iii.worker.yamldefines how the engine should provision a worker sandbox (language runtime, entry point, resource limits, install/start scripts), whileiii.workers.yamldeclares pre-built worker images that can be pulled and launched by the engine. The Dockerfile uses a two-stage build with cross-compilation to produce minimal Debian-based images for both x86_64 and ARM64 targets.Summary by CodeRabbit
New Features
Chores